// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/themes/theme_service_factory.h"

#include "base/no_destructor.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "cef/libcef/features/runtime.h"
#include "chrome/browser/extensions/extension_system_factory.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/common/pref_names.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "extensions/browser/extension_prefs_factory.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_factory.h"

#if BUILDFLAG(IS_WIN)
#include "chrome/browser/themes/theme_helper_win.h"
#endif

// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chrome/browser/themes/theme_service_aura_linux.h"
#include "ui/views/linux_ui/linux_ui.h"
#endif

#if BUILDFLAG(ENABLE_CEF)
#include "cef/libcef/common/extensions/extensions_util.h"
#endif

namespace {

const ThemeHelper& GetThemeHelper() {
#if BUILDFLAG(IS_WIN)
  using ThemeHelper = ThemeHelperWin;
#endif

  static base::NoDestructor<std::unique_ptr<ThemeHelper>> theme_helper(
      std::make_unique<ThemeHelper>());
  return **theme_helper;
}

}  // namespace

// static
ThemeService* ThemeServiceFactory::GetForProfile(Profile* profile) {
  return static_cast<ThemeService*>(
      GetInstance()->GetServiceForBrowserContext(profile, true));
}

// static
const extensions::Extension* ThemeServiceFactory::GetThemeForProfile(
    Profile* profile) {
  ThemeService* theme_service = GetForProfile(profile);
  if (!theme_service->UsingExtensionTheme())
    return nullptr;

  return extensions::ExtensionRegistry::Get(profile)
      ->enabled_extensions()
      .GetByID(theme_service->GetThemeID());
}

// static
ThemeServiceFactory* ThemeServiceFactory::GetInstance() {
  return base::Singleton<ThemeServiceFactory>::get();
}

ThemeServiceFactory::ThemeServiceFactory()
    : BrowserContextKeyedServiceFactory(
          "ThemeService",
          BrowserContextDependencyManager::GetInstance()) {
  DependsOn(extensions::ExtensionRegistryFactory::GetInstance());
  DependsOn(extensions::ExtensionPrefsFactory::GetInstance());
#if BUILDFLAG(ENABLE_CEF)
  const bool extensions_disabled = cef::IsAlloyRuntimeEnabled() &&
                                   !extensions::ExtensionsEnabled();
#else
  const bool extensions_disabled = false;
#endif
  if (!extensions_disabled) {
  DependsOn(extensions::ExtensionSystemFactory::GetInstance());
  }
}

ThemeServiceFactory::~ThemeServiceFactory() {}

KeyedService* ThemeServiceFactory::BuildServiceInstanceFor(
    content::BrowserContext* profile) const {
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
  using ThemeService = ThemeServiceAuraLinux;
#endif

  auto provider = std::make_unique<ThemeService>(static_cast<Profile*>(profile),
                                                 GetThemeHelper());
  provider->Init();
  return provider.release();
}

void ThemeServiceFactory::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
  bool default_uses_system_theme = false;

  const views::LinuxUI* linux_ui = views::LinuxUI::instance();
  if (linux_ui)
    default_uses_system_theme = linux_ui->GetDefaultUsesSystemTheme();

  registry->RegisterBooleanPref(prefs::kUsesSystemTheme,
                                default_uses_system_theme);
#endif
  registry->RegisterFilePathPref(prefs::kCurrentThemePackFilename,
                                 base::FilePath());
  registry->RegisterStringPref(prefs::kCurrentThemeID,
                               ThemeHelper::kDefaultThemeID);
  registry->RegisterIntegerPref(prefs::kAutogeneratedThemeColor, 0);
  registry->RegisterIntegerPref(prefs::kPolicyThemeColor, SK_ColorTRANSPARENT);
}

content::BrowserContext* ThemeServiceFactory::GetBrowserContextToUse(
    content::BrowserContext* context) const {
  return chrome::GetBrowserContextRedirectedInIncognito(context);
}

bool ThemeServiceFactory::ServiceIsCreatedWithBrowserContext() const {
  return true;
}
